﻿#include "serviceutils.h"

QList<ServiceUtils::ServiceInfo> ServiceUtils::getInstalledServiceList(bool ascending,
                                                                       const QString &grepPattern,
                                                                       const QString &state) {
    QMap<QString, ServiceInfo> serviceUnitFileList;

    QString stateFilter = state.trimmed();

    {
        QProcess process;
        QStringList environment;
        environment << "COLUMNS=1000";
        process.setEnvironment(environment);
        process.start("systemctl list-unit-files");
        process.waitForFinished();

        // 读取进程输出
        QString output = process.readAllStandardOutput();
        QStringList lines = output.split("\n");

        QRegularExpression packageRegex("^(\\S+)\\s+((?:\\S+\\s+)?)(.+)$");

        bool startParsing = false;
        QRegularExpression grepPatternRegex(grepPattern);
        foreach (const QString &line, lines) {
            if (!startParsing && line.trimmed().startsWith("UNIT FILE")) {
                startParsing = true;
                continue;
            }
            if (!startParsing) {
                continue;
            }

            if (line.isEmpty()) {
                break; // 已到最后一行
            }
            QRegularExpressionMatch match = packageRegex.match(line);
            if (match.hasMatch()) {
                ServiceInfo serviceInfo;

                serviceInfo.serviceName = match.captured(1).trimmed();
                serviceInfo.serviceState = match.captured(2).trimmed();

                if (!grepPattern.isEmpty()
                    && !grepPatternRegex.match(serviceInfo.serviceName).hasMatch()) {
                    continue;
                }

                if (!stateFilter.isEmpty() && stateFilter != serviceInfo.serviceState) {
                    continue;
                }
                serviceUnitFileList[serviceInfo.serviceName] = serviceInfo;
            }
        }
    }

    QMap<QString, ServiceInfo> serviceUnitList;
    {
        QProcess process;
        QStringList environment;
        environment << "COLUMNS=1000";
        process.setEnvironment(environment);
        process.start("systemctl list-units --full --all");
        process.waitForFinished();

        // 读取进程输出
        QString output = process.readAllStandardOutput();
        QStringList lines = output.split("\n");

        QRegularExpression packageRegex("^\\s*●?\\s*(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(.+)$");

        bool startParsing = false;
        QRegularExpression grepPatternRegex(grepPattern);
        foreach (const QString &line, lines) {
            if (!startParsing && line.trimmed().startsWith("UNIT")) {
                startParsing = true;
                continue;
            }
            if (!startParsing) {
                continue;
            }

            if (line.isEmpty()) {
                break; // 已到最后一行
            }
            QRegularExpressionMatch match = packageRegex.match(line);
            if (match.hasMatch()) {
                QStringList tt = match.capturedTexts();
                ServiceInfo serviceInfo;

                serviceInfo.serviceName = match.captured(1).trimmed();
                serviceInfo.load = match.captured(2).trimmed();
                serviceInfo.active = match.captured(3).trimmed();
                serviceInfo.sub = match.captured(4).trimmed();
                serviceInfo.description = match.captured(5).trimmed();

                if (!grepPattern.isEmpty()
                    && !grepPatternRegex.match(serviceInfo.serviceName).hasMatch()) {
                    continue;
                }

                serviceUnitList[serviceInfo.serviceName] = serviceInfo;
            }
        }
    }

    QMap<QString, ServiceUtils::ServiceInfo>::const_iterator it;
    for (it = serviceUnitFileList.constBegin(); it != serviceUnitFileList.constEnd(); ++it) {
        const QString &key = it.key(); // Accessing the key
        ServiceUtils::ServiceInfo &info = serviceUnitFileList[key];

        if (serviceUnitList.contains(key)) {
            ServiceInfo &otherInfo = serviceUnitList[key];
            info.sub = otherInfo.sub;
            info.load = otherInfo.load;
            info.active = otherInfo.active;
            info.description = otherInfo.description;
        }
    }

    QList<ServiceInfo> serviceInfoList = serviceUnitFileList.values();

    // 根据排序字段和排序方式进行排序
    std::sort(serviceInfoList.begin(), serviceInfoList.end(),
              [&](const ServiceInfo &pkg1, const ServiceInfo &pkg2) {
                  QString field1 = pkg1.serviceName;
                  QString field2 = pkg2.serviceName;
                  return ascending ? field1 < field2 : field1 > field2;
              });

    return serviceInfoList;
}

QPair<int, QList<ServiceUtils::ServiceInfo>>
ServiceUtils::getInstalledServiceList(bool ascending, const QString &grepPattern, int pageNum,
                                      int pageSize, const QString &state) {
    QList<ServiceUtils::ServiceInfo> fullServiceList =
        getInstalledServiceList(ascending, grepPattern, state);

    // Implement pagination
    int startIdx = (pageNum - 1) * pageSize;
    int endIdx = qMin(startIdx + pageSize, static_cast<int>(fullServiceList.size()));

    QList<ServiceInfo> paginatedList(fullServiceList.begin() + startIdx,
                                     fullServiceList.begin() + endIdx);

    return qMakePair(fullServiceList.size(), paginatedList);
}

ShellUtils::ShellResult ServiceUtils::status(const QString &serviceName) {
    if (AppCommon::isNullOrEmpty(serviceName)) {
        return ShellUtils::ShellResult::errorResult(QObject::tr("服务名为空"), 0);
    }

    QStringList commands;
    commands << "status";
    commands << serviceName;
    return ShellUtils::runCommand("systemctl", commands);
}

ShellUtils::ShellResult ServiceUtils::operate(const QString &serviceName,
                                              const QString &operateType) {
    if (AppCommon::isNullOrEmpty(serviceName) || AppCommon::isNullOrEmpty(operateType)) {
        return ShellUtils::ShellResult::errorResult(QObject::tr("操作或服务名为空"), 0);
    }
    QStringList args;
    args << "systemctl";
    args << operateType;
    args << serviceName;
    if (operateType == "status") {
        args << "-l";
        args << "--no-pager";
    }
    ShellUtils::ShellResult result = ShellUtils::runCommand("sudo", args);
    if (operateType == "status") {
        if (result.exitCode == 3) {
            result.result = result.cmdResult;
            result.success = true;
        }
    }
    return result;
}

ShellUtils::ShellResult ServiceUtils::reload() {
    QStringList args;
    args << "systemctl";
    args << "daemon-reload";
    return ShellUtils::runCommand("sudo", args);
}

bool ServiceUtils::isEnabled(const QString &serviceName) {
    if (AppCommon::isNullOrEmpty(serviceName)) {
        return false;
    }
    QStringList cmds;
    cmds << "systemctl";
    cmds << "is-enabled";
    cmds << serviceName;
    ShellUtils::ShellResult result = ShellUtils::runCommand(cmds);
    return result.success && result.cmdResult.contains("enabled");
}
